import { Asset, Component, _decorator,Node, game, director } from 'cc';
import { UpdatePanel } from './UpdatePanel';

const jsb = (<any>window).jsb;

// Custom manifest removed the following assets:
// 1. res/raw-assets/2a/2a40e5e7-4c4a-4350-9e5d-76757755cdd2.png
// 2. res/raw-assets/2d/2d86a854-63c4-4b90-8b88-a4328b8526c2.png
// So when custom manifest used, you should be able to find them in downloaded remote assets
var customManifestStr = JSON.stringify({
    "packageUrl": "http://192.168.1.27:5001/tutorial-hot-update/remote-assets/",
    "remoteManifestUrl": "http://192.168.1.27:5001/tutorial-hot-update/remote-assets/project.manifest",
    "remoteVersionUrl": "http://192.168.1.27:5001/tutorial-hot-update/remote-assets/version.manifest",
    "version": "1.0.0",
    "assets": {
        "src/application.js": {
            "size": 1252,
            "md5": "45b04eb91863b625eedaf44543f623dd"
        },
        "src/chunks/bundle.js": {
            "size": 1724,
            "md5": "0d2a3aa86b4d9d8592b8d23ae61134b0"
        },
        "src/cocos-js/assets/spine-a0005c42.wasm": {
            "size": 449470,
            "md5": "47d51e45b96f485324f470090255b099"
        },
        "src/cocos-js/cc.js": {
            "size": 4607299,
            "md5": "4c98cc9c71de7fae9f828d42e7ba3156"
        },
        "src/import-map.json": {
            "size": 51,
            "md5": "0a4b903dc20b74fe4a5a977a98b9d094"
        },
        "src/settings.json": {
            "size": 22374,
            "md5": "542bc003f286720a3efbd12b0f41d925"
        },
        "src/system.bundle.js": {
            "size": 26064,
            "md5": "4f6600b7c6bef663410c8135ce3c23bc"
        },
        "assets/BundleFile/cc.config.json": {
            "size": 2143,
            "md5": "114cd0f54b505eb4695d354706af6ad3"
        },
        "assets/BundleFile/import/05/053f91fd9.json": {
            "size": 147,
            "md5": "1eb138662741bb45f34126d5dac9409d"
        },
        "assets/BundleFile/import/87/87470da8-e3f2-4ab8-a506-c010831f0907.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/BundleFile/import/87/87470da8-e3f2-4ab8-a506-c010831f0907@f9941.json": {
            "size": 569,
            "md5": "d95e9a439217f2fa5ccf429a7b2dc36b"
        },
        "assets/BundleFile/import/88/887e185a-1fd9-4c2c-a4f4-9621323b16b1.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/BundleFile/import/88/887e185a-1fd9-4c2c-a4f4-9621323b16b1@f9941.json": {
            "size": 569,
            "md5": "4cf5eed7aaebe89bb348d8a01eca5f97"
        },
        "assets/BundleFile/index.js": {
            "size": 627,
            "md5": "c78610369a1c16a903a926edc059e69e"
        },
        "assets/BundleFile/native/87/87470da8-e3f2-4ab8-a506-c010831f0907.png": {
            "size": 4763,
            "md5": "88a09425e506248e94dd8056944f347a"
        },
        "assets/BundleFile/native/88/887e185a-1fd9-4c2c-a4f4-9621323b16b1.png": {
            "size": 5531,
            "md5": "0bbcbcd0a98002cb089842eed4993be0"
        },
        "assets/internal/cc.config.json": {
            "size": 6208,
            "md5": "56d6c5269f9b3a79b32b168d2eaa50eb"
        },
        "assets/internal/import/0c/0ca60d3e4.json": {
            "size": 158345,
            "md5": "df017d589e9831729249844ba80f9526"
        },
        "assets/internal/index.js": {
            "size": 621,
            "md5": "eeb02efca156b4767578137ea52124ba"
        },
        "assets/main/cc.config.json": {
            "size": 5432,
            "md5": "4a7a4b556812c0e55f3fbb2bef990275"
        },
        "assets/main/import/02/02bc80361.json": {
            "size": 10080,
            "md5": "f3ca8d87230900df1ea7af9abb22c358"
        },
        "assets/main/import/04/042beadb4.json": {
            "size": 432,
            "md5": "90032fcc04d722791a566da3aa764220"
        },
        "assets/main/import/20/20835ba4-6145-4fbc-a58a-051ce700aa3e.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/main/import/24/24a704da-2867-446d-8d1a-5e920c75e09d.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/main/import/54/544e49d6-3f05-4fa8-9a9e-091f98fc2ce8.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/main/import/7d/7d8f9b89-4fd1-4c9f-a3ab-38ec7cded7ca.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/main/import/95/951249e0-9f16-456d-8b85-a6ca954da16b.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/main/import/9f/9fd900dd-221b-4f89-8f2c-fba34243c835.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/main/import/ba/ba21476f-2866-4f81-9c4d-6e359316e448.json": {
            "size": 192,
            "md5": "8bce784945efd554512e8520ec9caccb"
        },
        "assets/main/import/d8/d8b59413-5481-4497-86c7-810217ee2b23.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/main/import/fd/fd8ec536-a354-4a17-9c74-4f3883c378c8.json": {
            "size": 480,
            "md5": "731f44a39ce9377ee6de8ba34edaf039"
        },
        "assets/main/index.js": {
            "size": 51785,
            "md5": "a66f1f1932c941c21b7c0f029dacd521"
        },
        "assets/main/native/20/20835ba4-6145-4fbc-a58a-051ce700aa3e.png": {
            "size": 1082,
            "md5": "90cf45d059d0408bec327f66eae5764c"
        },
        "assets/main/native/24/24a704da-2867-446d-8d1a-5e920c75e09d.png": {
            "size": 1140,
            "md5": "a4b5953dffeb145b4b70072d91c4052b"
        },
        "assets/main/native/54/544e49d6-3f05-4fa8-9a9e-091f98fc2ce8.png": {
            "size": 1114,
            "md5": "83fcc9912e01ae5411c357651fb8b1cf"
        },
        "assets/main/native/7d/7d8f9b89-4fd1-4c9f-a3ab-38ec7cded7ca.png": {
            "size": 82,
            "md5": "cea68f0d7cba38440224f6f74531e2d8"
        },
        "assets/main/native/95/951249e0-9f16-456d-8b85-a6ca954da16b.png": {
            "size": 1050,
            "md5": "c06a93f5f1a8a1c6edc4fd8b52e96cbf"
        },
        "assets/main/native/9f/9fd900dd-221b-4f89-8f2c-fba34243c835.png": {
            "size": 1177,
            "md5": "d1118d133683bb4227d5e60c79c846b7"
        },
        "assets/main/native/a2/a215a380-20d9-42eb-b262-2d22da4cf0b2.manifest": {
            "size": 11492,
            "md5": "f72911eb083de075606080c22d920260"
        },
        "assets/main/native/d8/d8b59413-5481-4497-86c7-810217ee2b23.png": {
            "size": 37864,
            "md5": "55ea4e952bf080f300379ec26723598b"
        },
        "assets/resources/cc.config.json": {
            "size": 14850,
            "md5": "b7eb165384bbd24da2c70776a323aa90"
        },
        "assets/resources/import/03/035f0ec0-0280-4dfe-99d0-68886e1aaa49.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/03/035f0ec0-0280-4dfe-99d0-68886e1aaa49@f9941.json": {
            "size": 584,
            "md5": "f91443832ca9d9929f125c239b4dbcaa"
        },
        "assets/resources/import/04/0428e4b4-c324-4286-8f58-50374ec15ef8.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/04/0428e4b4-c324-4286-8f58-50374ec15ef8@f9941.json": {
            "size": 573,
            "md5": "b8acd642719be1cba84e47720a7b8b15"
        },
        "assets/resources/import/04/0452e50f7.json": {
            "size": 1002,
            "md5": "3783adec45188ea3784c31332a5a3f5f"
        },
        "assets/resources/import/05/0519d0f0-f80f-4ae1-9255-b58db547608a.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/05/0519d0f0-f80f-4ae1-9255-b58db547608a@f9941.json": {
            "size": 568,
            "md5": "60999560bc5413a8d65275201ede9a5b"
        },
        "assets/resources/import/17/178f6b64-dcd3-4879-9ce3-e2dd8beeaf9a.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/17/178f6b64-dcd3-4879-9ce3-e2dd8beeaf9a@f9941.json": {
            "size": 584,
            "md5": "ed6d1a048b05b4fb522b940f2e032f68"
        },
        "assets/resources/import/27/2715e76b-5af6-421d-86d4-5e93fb90f9a2.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/27/2715e76b-5af6-421d-86d4-5e93fb90f9a2@f9941.json": {
            "size": 566,
            "md5": "29353224ec5cbdf49b338baa22eac78b"
        },
        "assets/resources/import/53/5360ef93-8e30-45ac-8438-a6e7b622a916.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/53/5360ef93-8e30-45ac-8438-a6e7b622a916@f9941.json": {
            "size": 585,
            "md5": "b93e0e883c7d6216ef1d6ea368b60bb9"
        },
        "assets/resources/import/64/647fdebd-2382-4c17-8332-7c91993ea56c.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/64/647fdebd-2382-4c17-8332-7c91993ea56c@f9941.json": {
            "size": 568,
            "md5": "dc51208ba6ce851afec7566b0a7c3ebf"
        },
        "assets/resources/import/6f/6febcdfb-cf04-4c9a-a154-b52e7b427f95.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/6f/6febcdfb-cf04-4c9a-a154-b52e7b427f95@f9941.json": {
            "size": 584,
            "md5": "1e047d1bbc228714eefe10aea6048061"
        },
        "assets/resources/import/93/9310ec07-d2fd-4186-a2ab-00494f7a8b51.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/93/9310ec07-d2fd-4186-a2ab-00494f7a8b51@f9941.json": {
            "size": 568,
            "md5": "6f3ce20e2eafee61e6c18f27997a080a"
        },
        "assets/resources/import/9e/9e791390-8b60-4cde-b390-84b2a9bae0c1.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/9e/9e791390-8b60-4cde-b390-84b2a9bae0c1@f9941.json": {
            "size": 568,
            "md5": "aa3e35f648a3c7aedf9d776c0cb7dc19"
        },
        "assets/resources/import/9f/9ffb2f51-9612-4dbd-b88c-93b9b5849b86.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/9f/9ffb2f51-9612-4dbd-b88c-93b9b5849b86@f9941.json": {
            "size": 568,
            "md5": "a1dfb02c7c6640015dbc2ae2c7694b98"
        },
        "assets/resources/import/b0/b0ec3364-bc18-4449-9d95-327146793160.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/b0/b0ec3364-bc18-4449-9d95-327146793160@f9941.json": {
            "size": 566,
            "md5": "2db3a5876bdde081a17fa179d50514b1"
        },
        "assets/resources/import/be/bed84629-be6e-4d68-8f29-44e115b625f4.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/be/bed84629-be6e-4d68-8f29-44e115b625f4@f9941.json": {
            "size": 566,
            "md5": "93b9e4a56ed592c52ac93c345efb2201"
        },
        "assets/resources/import/c2/c2b771c6-093c-4659-b81a-91c85c17cf50.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/c2/c2b771c6-093c-4659-b81a-91c85c17cf50@f9941.json": {
            "size": 568,
            "md5": "738a986f0f3d6fead956a97fbafef28d"
        },
        "assets/resources/import/cb/cb442251-2e03-4cdf-b22b-e95eedef340d.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/cb/cb442251-2e03-4cdf-b22b-e95eedef340d@f9941.json": {
            "size": 568,
            "md5": "f7aedaed449686478c4a54232c0b0ba8"
        },
        "assets/resources/import/f0/f0cf0b34-82aa-461d-be49-b501a8fd369a.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/f0/f0cf0b34-82aa-461d-be49-b501a8fd369a@f9941.json": {
            "size": 585,
            "md5": "20a835fd869c544f11f92723f73acb28"
        },
        "assets/resources/import/fe/fecfc62f-02e6-4547-a454-c97fd7f8ecbb.json": {
            "size": 72,
            "md5": "a253314ec7107d95345d7fc89b8d7bb5"
        },
        "assets/resources/import/fe/fecfc62f-02e6-4547-a454-c97fd7f8ecbb@f9941.json": {
            "size": 554,
            "md5": "a1790f5359ad650cd255896e3fe4f4d8"
        },
        "assets/resources/index.js": {
            "size": 624,
            "md5": "d7916efc3fa8f57fb7b79ac9af0b1c68"
        },
        "assets/resources/native/03/035f0ec0-0280-4dfe-99d0-68886e1aaa49.png": {
            "size": 25917,
            "md5": "af9b4969827d12613ec16c854ff70c20"
        },
        "assets/resources/native/04/0428e4b4-c324-4286-8f58-50374ec15ef8.png": {
            "size": 36079,
            "md5": "215b38b99e6868984e4ec65838cf21ee"
        },
        "assets/resources/native/05/0519d0f0-f80f-4ae1-9255-b58db547608a.png": {
            "size": 6775,
            "md5": "6223b8efd64ba9a4173eb0b39441c870"
        },
        "assets/resources/native/17/178f6b64-dcd3-4879-9ce3-e2dd8beeaf9a.png": {
            "size": 25056,
            "md5": "489dcce995c803ca30ba33cd0a47fff3"
        },
        "assets/resources/native/27/2715e76b-5af6-421d-86d4-5e93fb90f9a2.png": {
            "size": 10771,
            "md5": "5bf8637eca33f26fc1761f0cb324c957"
        },
        "assets/resources/native/53/5360ef93-8e30-45ac-8438-a6e7b622a916.png": {
            "size": 27247,
            "md5": "688a7665921828ade8530005c9824736"
        },
        "assets/resources/native/64/647fdebd-2382-4c17-8332-7c91993ea56c.png": {
            "size": 5414,
            "md5": "b9ece2ec3f8fd95df979a7fbf74257f6"
        },
        "assets/resources/native/6f/6febcdfb-cf04-4c9a-a154-b52e7b427f95.png": {
            "size": 25307,
            "md5": "7849a0317627810cc3787e47f5d9d7e0"
        },
        "assets/resources/native/93/9310ec07-d2fd-4186-a2ab-00494f7a8b51.png": {
            "size": 8213,
            "md5": "598dafb3b1b704e3214fa1c2a6ae5e13"
        },
        "assets/resources/native/9e/9e791390-8b60-4cde-b390-84b2a9bae0c1.png": {
            "size": 12288,
            "md5": "0c3a8562fa979aa25fb737303519e2b5"
        },
        "assets/resources/native/9f/9ffb2f51-9612-4dbd-b88c-93b9b5849b86.png": {
            "size": 3974,
            "md5": "6a0db1e2cb44fd4eb59ea58d18d35744"
        },
        "assets/resources/native/b0/b0ec3364-bc18-4449-9d95-327146793160.png": {
            "size": 11999,
            "md5": "c21a3419a43cdbee27c64f1161cefd3e"
        },
        "assets/resources/native/be/bed84629-be6e-4d68-8f29-44e115b625f4.png": {
            "size": 10937,
            "md5": "5cec6d1ec4c0eb6f43d4e18f0a6225e3"
        },
        "assets/resources/native/c2/c2b771c6-093c-4659-b81a-91c85c17cf50.png": {
            "size": 5512,
            "md5": "2eeaf8c4bf29bc4040b43b59aeb13900"
        },
        "assets/resources/native/cb/cb442251-2e03-4cdf-b22b-e95eedef340d.png": {
            "size": 7743,
            "md5": "fc89d2c9890b128433b0520f4c7685c2"
        },
        "assets/resources/native/f0/f0cf0b34-82aa-461d-be49-b501a8fd369a.png": {
            "size": 34973,
            "md5": "3a6876a1dda52acb619f9f90b02cf324"
        },
        "assets/resources/native/fe/fecfc62f-02e6-4547-a454-c97fd7f8ecbb.png": {
            "size": 12115,
            "md5": "3706c58cf3a32908c72d1360ac082268"
        },
        "jsb-adapter/engine-adapter.js": {
            "size": 166301,
            "md5": "353e3bb2addf71ec5a7e81a026e09705"
        },
        "jsb-adapter/web-adapter.js": {
            "size": 173350,
            "md5": "a0b86fcdb473c788e794b331bbc6fcd1"
        }
    },
    "searchPaths": []
});


const { ccclass, property } = _decorator;

@ccclass
export class HotUpdate extends Component {

    @property(UpdatePanel)
    panel: UpdatePanel = null!;

    @property(Asset)
    manifestUrl: Asset = null!;

    @property(Node)
    updateUI: Node = null!;

    private _updating = false;
    private _canRetry = false;
    private _storagePath = '';
    private _am: jsb.AssetsManager = null!;
    private _checkListener = null;
    private _updateListener = null;
    private _failCount = 0;
    private versionCompareHandle: (versionA: string, versionB: string) => number = null!;

    checkCb(event: any) {
        console.log('Code: ' + event.type);
        switch (event.type) {
            case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                this.panel.info.string = "No local manifest file found, hot update skipped.";
                break;
            case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
            case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                this.panel.info.string = "Fail to download manifest file, hot update skipped.";
                break;
            case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                this.panel.info.string = "Already up to date with the latest remote version.";
                break;
            case jsb.EventAssetsManager.NEW_VERSION_FOUND:
                this.panel.info.string = 'New version found, please try to update. (' + Math.ceil(this._am.getTotalBytes() / 1024) + 'kb)';
                this.panel.checkBtn.active = false;
                this.panel.fileProgress.progress = 0;
                this.panel.byteProgress.progress = 0;
                break;
            default:
                return;
        }


        this._am.setEventCallback(null!);
        this._checkListener = null;
        this._updating = false;
    }

    updateCb(event: any) {
        var needRestart = false;
        var failed = false;
        switch (event.type) {
            case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                this.panel.info.string = 'No local manifest file found, hot update skipped.';
                failed = true;
                break;
            case jsb.EventAssetsManager.UPDATE_PROGRESSION:
                this.panel.byteProgress.progress = event.getPercent();
                this.panel.fileProgress.progress = event.getPercentByFile();

                this.panel.fileLabel.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
                this.panel.byteLabel.string = event.getDownloadedBytes() + ' / ' + event.getTotalBytes();
                console.log(this.panel.fileLabel.string, this.panel.byteLabel.string);
                var msg = event.getMessage();
                if (msg) {
                    this.panel.info.string = 'Updated file: ' + msg;
                    // cc.log(event.getPercent()/100 + '% : ' + msg);
                }
                break;
            case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
            case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                this.panel.info.string = 'Fail to download manifest file, hot update skipped.';
                failed = true;
                break;
            case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                this.panel.info.string = 'Already up to date with the latest remote version.';
                failed = true;
                break;
            case jsb.EventAssetsManager.UPDATE_FINISHED:
                this.panel.info.string = 'Update finished. ' + event.getMessage();
                needRestart = true;
                break;
            case jsb.EventAssetsManager.UPDATE_FAILED:
                this.panel.info.string = 'Update failed. ' + event.getMessage();
                this.panel.retryBtn.active = true;
                this._updating = false;
                this._canRetry = true;
                break;
            case jsb.EventAssetsManager.ERROR_UPDATING:
                this.panel.info.string = 'Asset update error: ' + event.getAssetId() + ', ' + event.getMessage();
                break;
            case jsb.EventAssetsManager.ERROR_DECOMPRESS:
                this.panel.info.string = event.getMessage();
                break;
            default:
                break;
        }

        if (failed) {
            this._am.setEventCallback(null!);
            this._updateListener = null;
            this._updating = false;
        }

        if (needRestart) {
            this._am.setEventCallback(null!);
            this._updateListener = null;
            // Prepend the manifest's search path
            var searchPaths = jsb.fileUtils.getSearchPaths();
            var newPaths = this._am.getLocalManifest().getSearchPaths();
            console.log(JSON.stringify(newPaths));
            Array.prototype.unshift.apply(searchPaths, newPaths);
            // This value will be retrieved and appended to the default search path during game startup,
            // please refer to samples/js-tests/main.js for detailed usage.
            // !!! Re-add the search paths in main.js is very important, otherwise, new scripts won't take effect.
            localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
            jsb.fileUtils.setSearchPaths(searchPaths);

            // restart game.
            setTimeout(() => {
                game.restart();
            }, 1000)
        }
    }

    loadCustomManifest() {
        if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
            var manifest = new jsb.Manifest(customManifestStr, this._storagePath);
            this._am.loadLocalManifest(manifest, this._storagePath);
            this.panel.info.string = 'Using custom manifest';
        }
    }

    retry() {
        if (!this._updating && this._canRetry) {
            this.panel.retryBtn.active = false;
            this._canRetry = false;

            this.panel.info.string = 'Retry failed Assets...';
            this._am.downloadFailedAssets();
        }
    }

    checkUpdate() {
        if (this._updating) {
            this.panel.info.string = 'Checking or updating ...';
            return;
        }
        if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
            var url = this.manifestUrl.nativeUrl;
            this._am.loadLocalManifest(url);
        }
        if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
            this.panel.info.string = 'Failed to load local manifest ...';
            return;
        }
        this._am.setEventCallback(this.checkCb.bind(this));

        this._am.checkUpdate();
        this._updating = true;
    }

    hotUpdate() {
        if (this._am && !this._updating) {
            this._am.setEventCallback(this.updateCb.bind(this));

            if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
                var url = this.manifestUrl.nativeUrl;
                this._am.loadLocalManifest(url);
            }

            this._failCount = 0;
            this._am.update();
            this.panel.updateBtn.active = false;
            this._updating = true;
        }
    }

    show() {
        if (this.updateUI.active === false) {
            this.updateUI.active = true;
        }
    }

    // use this for initialization
    onLoad() {
        // Hot update is only available in Native build
        if (!jsb) {
            return;
        }
        this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'blackjack-remote-asset');
        console.log('Storage path for remote asset : ' + this._storagePath);
 
        // Setup your own version compare handler, versionA and B is versions in string
        // if the return value greater than 0, versionA is greater than B,
        // if the return value equals 0, versionA equals to B,
        // if the return value smaller than 0, versionA is smaller than B.
        this.versionCompareHandle = function (versionA: string, versionB: string) {
            console.log("JS Custom Version Compare: version A is " + versionA + ', version B is ' + versionB);
            var vA = versionA.split('.');
            var vB = versionB.split('.');
            for (var i = 0; i < vA.length; ++i) {
                var a = parseInt(vA[i]);
                var b = parseInt(vB[i] || '0');
                if (a === b) {
                    continue;
                }
                else {
                    return a - b;
                }
            }
            if (vB.length > vA.length) {
                return -1;
            }
            else {
                return 0;
            }
        };

        // Init with empty manifest url for testing custom manifest
        this._am = new jsb.AssetsManager('', this._storagePath, this.versionCompareHandle);

        var panel = this.panel;
        // Setup the verification callback, but we don't have md5 check function yet, so only print some message
        // Return true if the verification passed, otherwise return false
        this._am.setVerifyCallback(function (path: string, asset: any) {
            // When asset is compressed, we don't need to check its md5, because zip file have been deleted.
            var compressed = asset.compressed;
            // Retrieve the correct md5 value.
            var expectedMD5 = asset.md5;
            // asset.path is relative path and path is absolute.
            var relativePath = asset.path;
            // The size of asset file, but this value could be absent.
            var size = asset.size;
            if (compressed) {
                panel.info.string = "Verification passed : " + relativePath;
                return true;
            }
            else {
                panel.info.string = "Verification passed : " + relativePath + ' (' + expectedMD5 + ')';
                return true;
            }
        });

        this.panel.info.string = 'Hot update is ready, please check or directly update.';
        this.panel.fileProgress.progress = 0;
        this.panel.byteProgress.progress = 0;
    }

    onDestroy() {
        if (this._updateListener) {
            this._am.setEventCallback(null!);
            this._updateListener = null;
        }
    }
}
